package nrpc.message;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;

import message.AbstractMessageParser;
import message.MessageParser;
import message.MessageParserSupplier;
import message.preset.StringMessageParser;
import message.reflect.HandlerMapper;
import nrpc.message.meta.InvokeMessage;
import nrpc.util.AsynMethodTool;

public class InvokeMessageParserSupplier implements MessageParserSupplier {


	private MessageParserSupplier[] suppliers;
	private HandlerMapper mapper;
	private int len = 0;
	
	public InvokeMessageParserSupplier(HandlerMapper mapper, Method method) {
		this.mapper = mapper;
		Parameter[] raw = method.getParameters();

		// 异步回调调用忽略最后一个参数
		if(AsynMethodTool.isAsyn(method) && AsynMethodTool.isCallback(method)) len = raw.length - 1;
		else len = raw.length;
		
		suppliers = new MessageParserSupplier[len];
		for(int i = 0; i<len; i++) 
			suppliers[i] = mapper.getParserSupplier(raw[i].getParameterizedType());
	}
	
	@Override
	public MessageParser parse(Object obj) {
		return new AbstractMessageParser(obj) {
			private int step = 0;
			private int i = 0;
			private StringMessageParser sparser;
			private MessageParser[] parsers = new MessageParser[len];
			{
				InvokeMessage message = (InvokeMessage)obj;
				sparser = new StringMessageParser(message.name, mapper);
				for(int i = 0; i<len; i++) {
					parsers[i] = suppliers[i].parse(message.args.get(i));
				}
			}
			@Override
			public boolean write(ByteBuffer byteBuffer) {
				switch(step) {
				case 0:
					try {
						byteBuffer.putInt(((InvokeMessage)obj).label);
					} catch (BufferOverflowException e) {
						return false;
					}
					step++;
				case 1:
					if(!(sparser.write(byteBuffer))) return false;
					step++;
				case 2:
					while(i < len) {
						if(!(parsers[i].write(byteBuffer))) return false;
						i++;
					}
					step++;
				}
				return true;
			}
		};
	}

}
